#include "QPropertyWidget.h"


void QPropertyWidget::createFreeWidget(void)
{
    freeWidget = new QWidget;
    freeLayout = new QVBoxLayout;

    QVBoxLayout *innerFreeLayout = new QVBoxLayout;

    QLabel *gridLabel = new QLabel("Grid step:");
    QSpinBox *gridSpinBox = new QSpinBox;
    gridSpinBox->setRange(10, 100);
    connect(gridSpinBox, SIGNAL(valueChanged(int)), this, SLOT(setGridStep(int)));
    gridSpinBox->setValue(20);
    gridSpinBox->setSuffix(" px");

    QHBoxLayout *gridLayout = new QHBoxLayout;
    gridLayout->addWidget(gridLabel);
    gridLayout->addWidget(gridSpinBox);
    innerFreeLayout->addLayout(gridLayout);

    QCheckBox *bindingCheckBox = new QCheckBox("Has binding");
    connect(bindingCheckBox, SIGNAL(toggled(bool)), this, SLOT(setBinding(bool)));
    innerFreeLayout->addWidget(bindingCheckBox);

    innerFreeLayout->addStretch(1);
    QGroupBox *groupBox = new QGroupBox("Options");
    groupBox->setLayout(innerFreeLayout);

    freeLayout->addWidget(groupBox);

    freeWidget->setLayout(freeLayout);
}
void QPropertyWidget::createNodeWidget(void)
{
    nodeWidget = new QWidget;
    nodeLayout = new QVBoxLayout;
    nodePropertyLayout = new QVBoxLayout;
    nodeComboBox = new QComboBox;
    connect(nodeComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(selectNode(int)));

    connectionAddButton = new QPushButton("Add nerve connection");
    connect(connectionAddButton, SIGNAL(clicked()), this, SLOT(addConnection()));

    connectionRemoveButton = new QPushButton("Remove nerve connection");
    connectionRemoveButton->setDisabled(true);
    connect(connectionRemoveButton, SIGNAL(clicked()), this, SLOT(removeConnection()));

    networkEditButton = new QPushButton("Edit nerve network");
    connect(networkEditButton, SIGNAL(clicked()), this, SLOT(editNetwork()));

    nodeRemoveButton = new QPushButton("Remove");
    nodeRemoveButton->setDisabled(true);
    connect(nodeRemoveButton, SIGNAL(clicked()), this, SLOT(removeNode()));

    nodeLayout->addWidget(nodeComboBox);
    nodeLayout->addStretch(1);
    nodeLayout->addLayout(nodePropertyLayout);
    nodeLayout->addStretch(2);
    nodeLayout->addWidget(connectionAddButton);
    nodeLayout->addWidget(connectionRemoveButton);
    nodeLayout->addWidget(networkEditButton);
    nodeLayout->addWidget(nodeRemoveButton);

    nodeWidget->setLayout(nodeLayout);
}
void QPropertyWidget::createMuscleWidget(void)
{
    muscleWidget = new QWidget;
    muscleLayout = new QVBoxLayout;
    musclePropertyLayout = new QVBoxLayout;
    muscleComboBox = new QComboBox;
    connect(muscleComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(selectMuscle(int)));
    muscleRemoveButton = new QPushButton("Remove");
    muscleRemoveButton->setDisabled(true);
    connect(muscleRemoveButton, SIGNAL(clicked()), this, SLOT(removeMuscle()));

    muscleLayout->addWidget(muscleComboBox);
    muscleLayout->addStretch(1);
    muscleLayout->addLayout(musclePropertyLayout);
    muscleLayout->addStretch(2);
    muscleLayout->addWidget(muscleRemoveButton);

    muscleWidget->setLayout(muscleLayout);
}
void QPropertyWidget::createNerveWidget(void)
{
    nerveWidget = new QWidget;
    nerveLayout = new QVBoxLayout;
    nervePropertyLayout = new QVBoxLayout;
    nerveComboBox = new QComboBox;
    connect(nerveComboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(selectNerve(int)));
    nerveRemoveButton = new QPushButton("Remove");
    nerveRemoveButton->setDisabled(true);
    connect(nerveRemoveButton, SIGNAL(clicked()), this, SLOT(removeNerve()));

    nerveLayout->addWidget(nerveComboBox);
    nerveLayout->addStretch(1);
    nerveLayout->addLayout(nervePropertyLayout);
    nerveLayout->addStretch(2);
    nerveLayout->addWidget(nerveRemoveButton);

    nerveWidget->setLayout(nerveLayout);
}

QPropertyWidget::QPropertyWidget(QWidget * /*parent*/ )
{
    type = -1;
    item = -1;

    exItem = -1;

    this->createFreeWidget();
    this->createNodeWidget();
    this->createMuscleWidget();
    this->createNerveWidget();

    tabWidget = new QTabWidget;
    tabWidget->setTabPosition(QTabWidget::West);
    tabWidget->addTab(freeWidget,"Free");
    tabWidget->addTab(nodeWidget,"Node");
    tabWidget->setTabEnabled(1, false);
    tabWidget->addTab(muscleWidget,"Muscle");
    tabWidget->setTabEnabled(2, false);
    tabWidget->addTab(nerveWidget,"Nerve");
    tabWidget->setTabEnabled(3, false);
    this->setType(0);

    mainLayout = new QVBoxLayout;
    mainLayout->setMargin(1);
    mainLayout->addWidget(tabWidget);
    this->setLayout(mainLayout);
}

void QPropertyWidget::addItem(QNode *node)
{
    if (!nodeRemoveButton->isEnabled()) nodeRemoveButton->setDisabled(false);
    if (!tabWidget->isTabEnabled(1)) tabWidget->setTabEnabled(1, true);

    QVBoxLayout *tempNodeLayout = new QVBoxLayout;

    QHBoxLayout *idLayout = new QHBoxLayout;
    idLayout->setMargin(2);
    QLabel *idLabel = new QLabel("Node ID: ");
    QLabel *idValueLabel = new QLabel;
    idValueLabel->setNum(node->getID());
    connect(node, SIGNAL(idChanged(int)), idValueLabel, SLOT(setNum(int)));
    idLayout->addWidget(idLabel);
    idLayout->addWidget(idValueLabel);
    idLayout->addStretch();
    tempNodeLayout->addLayout(idLayout);

    QLabel *posXLabel = new QLabel("xPos: ");
    QLabel *posXValue = new QLabel;
    posXValue->setNum(node->getPos().x());
    connect(node, SIGNAL(posXChanged(double)), posXValue, SLOT(setNum(double)));

    QHBoxLayout *posXLayout = new QHBoxLayout;
    posXLayout->addWidget(posXLabel);
    posXLayout->addWidget(posXValue);
    tempNodeLayout->addLayout(posXLayout);

    QLabel *posYLabel = new QLabel("yPos: ");
    QLabel *posYValue = new QLabel;
    posYValue->setNum(node->getPos().y());
    connect(node, SIGNAL(posYChanged(double)), posYValue, SLOT(setNum(double)));

    QHBoxLayout *posYLayout = new QHBoxLayout;
    posYLayout->addWidget(posYLabel);
    posYLayout->addWidget(posYValue);
    tempNodeLayout->addLayout(posYLayout);

    QLabel *posDotXLabel = new QLabel("xDot: ");
    QLabel *posDotXValue = new QLabel;
    posDotXValue->setNum(node->getPosDot().x());
    connect(node, SIGNAL(posDotXChanged(double)), posDotXValue, SLOT(setNum(double)));

    QHBoxLayout *posDotXLayout = new QHBoxLayout;
    posDotXLayout->addWidget(posDotXLabel);
    posDotXLayout->addWidget(posDotXValue);
    tempNodeLayout->addLayout(posDotXLayout);

    QLabel *posDotYLabel = new QLabel("yDot: ");
    QLabel *posDotYValue = new QLabel;
    posDotYValue->setNum(node->getPosDot().y());
    connect(node, SIGNAL(posDotYChanged(double)), posDotYValue, SLOT(setNum(double)));

    QHBoxLayout *posDotYLayout = new QHBoxLayout;
    posDotYLayout->addWidget(posDotYLabel);
    posDotYLayout->addWidget(posDotYValue);
    tempNodeLayout->addLayout(posDotYLayout);

    QCheckBox *isFixedCheckBox = new QCheckBox("Fixed");
    if (node->isFixed()) isFixedCheckBox->toggle();
    connect(isFixedCheckBox, SIGNAL(toggled(bool)), node, SLOT(setFixed(bool)));
    connect(node, SIGNAL(fixedStateChanged(bool)), isFixedCheckBox, SLOT(setChecked(bool)));
    tempNodeLayout->addWidget(isFixedCheckBox);

    QVBoxLayout *connectionLayout = new QVBoxLayout;
    QComboBox *comboBox = new QComboBox;
    connect(comboBox, SIGNAL(currentIndexChanged(int)), this, SLOT(selectConnection(int)));
    connectionComboBoxList << comboBox;

    connectionLayout->addWidget(comboBox);
    tempNodeLayout->addLayout(connectionLayout);

    QGroupBox *groupBox = new QGroupBox("Options");
    groupBox->setLayout(tempNodeLayout);
    groupBox->hide();
    nodeWidgetList << groupBox;

    nodePropertyLayout->addWidget(groupBox);

    nodeComboBox->addItem("Node ID: " + QString().setNum(node->getID()));
}
void QPropertyWidget::addItem(QAbstractMuscle *muscle)
{
    if (!muscleRemoveButton->isEnabled()) muscleRemoveButton->setDisabled(false);
    if (!tabWidget->isTabEnabled(2)) tabWidget->setTabEnabled(2, true);

    QVBoxLayout *tempMuscleLayout = new QVBoxLayout;

    QHBoxLayout *idLayout = new QHBoxLayout;
    QLabel *idLabel = new QLabel("Muscle ID: ");
    QLabel *idValueLabel = new QLabel;
    idValueLabel->setNum(muscle->getID());
    connect(muscle, SIGNAL(idChanged(int)), idValueLabel, SLOT(setNum(int)));
    idLayout->addWidget(idLabel);
    idLayout->addWidget(idValueLabel);
    idLayout->addStretch();
    tempMuscleLayout->addLayout(idLayout);

    QHBoxLayout *defLLayout = new QHBoxLayout;
    defLLayout->setMargin(1);
    QLabel *defLLabel = new QLabel("Set default l: ");
    QDoubleSpinBox *defLSpinBox = new QDoubleSpinBox;
    defLSpinBox->setRange(0, 9999);
    connect(muscle, SIGNAL(defLChanged(double)), defLSpinBox, SLOT(setValue(double)));
    connect(defLSpinBox, SIGNAL(valueChanged(double)), muscle, SLOT(setDefL(double)));
    defLLayout->addWidget(defLLabel);
    defLLayout->addWidget(defLSpinBox);
    tempMuscleLayout->addLayout(defLLayout);

    QHBoxLayout *kLayout = new QHBoxLayout;
    kLayout->setMargin(1);
    QLabel *kLabel = new QLabel("Set k: ");
    QDoubleSpinBox *kSpinBox = new QDoubleSpinBox;
    kSpinBox->setRange(0, 100);
    connect(muscle, SIGNAL(kChanged(double)), kSpinBox, SLOT(setValue(double)));
    connect(kSpinBox, SIGNAL(valueChanged(double)), muscle, SLOT(setK(double)));
    kLayout->addWidget(kLabel);
    kLayout->addWidget(kSpinBox);
    tempMuscleLayout->addLayout(kLayout);

    QGroupBox *tempGroupBox = new QGroupBox("Options");
    tempGroupBox->setLayout(tempMuscleLayout);
    tempGroupBox->hide();
    muscleWidgetList << tempGroupBox;

    muscle->emitEverything();

    musclePropertyLayout->addWidget(tempGroupBox);

    muscleComboBox->addItem("Muscle ID: " + QString().setNum(muscle->getID()));
}
void QPropertyWidget::addItem(QNerveTissue *nerve)
{
    if (!nerveRemoveButton->isEnabled()) nerveRemoveButton->setDisabled(false);
    if (!tabWidget->isTabEnabled(3)) tabWidget->setTabEnabled(3, true);

    QVBoxLayout *tempNerveLayout = new QVBoxLayout;

    QHBoxLayout *idLayout = new QHBoxLayout;
    idLayout->setMargin(2);
    QLabel *idLabel = new QLabel;
    switch (nerve->getType())
    {
    case 1:
        idLabel->setText("Neuron ID: ");
        break;
    case 2:
        idLabel->setText("Receptor ID: ");
        break;
    case 3:
        idLabel->setText("Transmitter ID: ");
        break;
    case 4:
        idLabel->setText("ElectricSynapse ID: ");
        break;
    case 5:
        idLabel->setText("IngibitorSynapse ID: ");
        break;
    case 6:
        idLabel->setText("ChemicalSynapse ID: ");
        break;
    }
    QLabel *idValueLabel = new QLabel;
    idValueLabel->setNum(nerve->getID());
    connect(nerve, SIGNAL(idChanged(int)), idValueLabel, SLOT(setNum(int)));
    idLayout->addWidget(idLabel);
    idLayout->addWidget(idValueLabel);
    idLayout->addStretch();
    tempNerveLayout->addLayout(idLayout);

    QHBoxLayout *pLayout = new QHBoxLayout;
    pLayout->setMargin(2);
    QLabel *pLabel = new QLabel(tr("memPot: "));
    QLabel *pValue = new QLabel;
    pValue->setNum(nerve->getMemPot());
    connect(nerve, SIGNAL(memPotChanged(double)), pValue, SLOT(setNum(double)));
    pLayout->addWidget(pLabel);
    pLayout->addWidget(pValue);
    tempNerveLayout->addLayout(pLayout);

    QHBoxLayout *layout = new QHBoxLayout;
    QPushButton *switchButton = new QPushButton(tr("Switch"));
    QLabel *switchLabel = new QLabel(nerve->getState());
    QDoubleSpinBox *spinBox = new QDoubleSpinBox;
    QLabel *label = new QLabel;

    QLabel *multLabel = new QLabel;
    QDoubleSpinBox *multSpinBox = new QDoubleSpinBox;
    QHBoxLayout *multLayout = new QHBoxLayout;

    switch (nerve->getType())
    {
    case 1:
        break;
    case 2:
        connect(switchButton, SIGNAL(clicked()), nerve, SLOT(switchMode()));

        connect(nerve, SIGNAL(stateChanged(QString)), switchLabel, SLOT(setText(QString)));
        layout->addWidget(switchButton);
        layout->addWidget(switchLabel);

        spinBox->setValue(nerve->getMemPot());
        connect(nerve, SIGNAL(memPotChanged(double)), spinBox, SLOT(setValue(double)));
        connect(spinBox, SIGNAL(valueChanged(double)), nerve, SLOT(setMemPot(double)));
        tempNerveLayout->addWidget(spinBox);
        tempNerveLayout->addLayout(layout);
        break;
    case 3:
        break;
    case 4:
        label->setText(tr("Conductance"));
        spinBox->setRange(0.01, 999);
        spinBox->setValue(nerve->getMultiplier());
        connect(spinBox, SIGNAL(valueChanged(double)), nerve, SLOT(setMultiplier(double)));
        connect(nerve, SIGNAL(multiplierChanged(double)), spinBox, SLOT(setValue(double)));
        layout->addWidget(label);
        layout->addWidget(spinBox);
        tempNerveLayout->addLayout(layout);
        break;
    case 5:
        multLabel->setText(tr("Multiplier"));
        multSpinBox->setRange(0.01, 99999);
        multSpinBox->setValue(nerve->getMultiplier());
        connect(multSpinBox, SIGNAL(valueChanged(double)), nerve, SLOT(setMultiplier(double)));
        connect(nerve, SIGNAL(multiplierChanged(double)), multSpinBox, SLOT(setValue(double)));
        multLayout->addWidget(multLabel);
        multLayout->addWidget(multSpinBox);

        label->setText("Relax Time");
        spinBox->setRange(0.01, 99999);
        spinBox->setValue(nerve->getRelaxTime());
        connect(spinBox, SIGNAL(valueChanged(double)), nerve, SLOT(setRelaxTime(double)));
        connect(nerve, SIGNAL(relaxTimeChanged(double)), spinBox, SLOT(setValue(double)));
        layout->addWidget(label);
        layout->addWidget(spinBox);
        tempNerveLayout->addLayout(multLayout);
        tempNerveLayout->addLayout(layout);
        break;
    case 6:
        label->setText("Relax Time");
        spinBox->setRange(0.01, 99999);
        spinBox->setValue(nerve->getRelaxTime());
        connect(spinBox, SIGNAL(valueChanged(double)), nerve, SLOT(setRelaxTime(double)));
        connect(nerve, SIGNAL(relaxTimeChanged(double)), spinBox, SLOT(setValue(double)));
        layout->addWidget(label);
        layout->addWidget(spinBox);
        tempNerveLayout->addLayout(layout);
        break;
    }

    QCheckBox *checkBox = new QCheckBox("Display curve");
    checkBox->setChecked(nerve->isCurveVisible());
    connect(checkBox, SIGNAL(toggled(bool)), this, SLOT(toggleCurve(bool)));
    connect(checkBox, SIGNAL(toggled(bool)), nerve, SLOT(toggleCurveVisible(bool)));
    connect(nerve, SIGNAL(curveVisibleToggled(bool)), checkBox, SLOT(setChecked(bool)));
    tempNerveLayout->addWidget(checkBox);

    QCheckBox *isSenderCheckBox = new QCheckBox("Is sender");
    isSenderCheckBox->setChecked(nerve->isSender());
    connect(isSenderCheckBox, SIGNAL(toggled(bool)), nerve, SLOT(toggleIsSender(bool)));
    tempNerveLayout->addWidget(isSenderCheckBox);

    QGroupBox *tempGroupBox = new QGroupBox("Options");
    tempGroupBox->setLayout(tempNerveLayout);
    tempGroupBox->hide();
    nerveWidgetList << tempGroupBox;

    nervePropertyLayout->addWidget(tempGroupBox);

    nerveComboBox->addItem(idLabel->text() + QString().setNum(nerve->getID()));
}

void QPropertyWidget::setGridStep(int _gridStep)
{
    emit gridStepChanged(_gridStep);
}
void QPropertyWidget::setBinding(bool _hasBinding)
{
    emit bindingChanged(_hasBinding);
}

void QPropertyWidget::selectConnection(int connection)
{
    if (connectionComboBoxList[nodeComboBox->currentIndex()]->currentIndex()>-1) connectionRemoveButton->setDisabled(false);
}

void QPropertyWidget::addConnection(void)
{
    emit addConnectionSignal(nodeComboBox->currentIndex());
}
void QPropertyWidget::addConnection(int sender, int channel, int receiver)
{
    connectionComboBoxList[sender]->addItem("Ch ID: " + QString().setNum(channel) + " muscle ID: " + QString().setNum(receiver));
}

void QPropertyWidget::removeConnection(void)
{
    QString string = connectionComboBoxList[nodeComboBox->currentIndex()]->currentText();
    QStringList list = string.split(QRegExp("\\s+"));

    bool ok = false;

    int channel = -1;
    int receiver = -1;

    int a = 0;

    for (int i=0; i<list.length(); ++i)
    {
        a = list[i].toInt(&ok);
        if (ok)
        {
            if (channel>=0) receiver = a;
            else channel = a;
        }
    }

    emit removeConnectionSignal(nodeComboBox->currentIndex(), channel, receiver);
}
void QPropertyWidget::removeConnection(int sender, int channel, int receiver)
{
    for (int i=0; i<connectionComboBoxList[sender]->count(); ++i)
    {
        if (connectionComboBoxList[sender]->itemText(i) == ("Ch ID: " + QString().setNum(channel) + " muscle ID: " + QString().setNum(receiver)))
        {
            connectionComboBoxList[sender]->removeItem(i);
        }
    }
}

void QPropertyWidget::editNetwork(void)
{
    emit editNetworkSignal(nodeComboBox->currentIndex());
}

void QPropertyWidget::removeNode(void)
{
    if (nodeComboBox->currentIndex()>-1)
    {
        emit removeNodeSignal(nodeComboBox->currentIndex());
    }
}
void QPropertyWidget::removeNode(int node)
{
    nodeWidgetList[node]->hide();
    nodePropertyLayout->removeWidget(nodeWidgetList[node]);
    connectionComboBoxList.removeAt(node);
    nodeWidgetList.removeAt(node);
    nodeComboBox->removeItem(node);

    for (int i=0; i<nodeComboBox->count(); ++i)
    {
        nodeComboBox->setItemText(i, nodeComboBox->itemText(i).replace(QRegExp("[0-9]{1,9}"), QString().setNum(i)));
    }

    if (connectionComboBoxList[nodeComboBox->currentIndex()]->currentIndex()>-1) connectionRemoveButton->setDisabled(false);
    else connectionRemoveButton->setDisabled(true);

    if (nodeComboBox->currentIndex()<0)
    {
        nodeRemoveButton->setDisabled(true);
        connectionRemoveButton->setDisabled(true);

        tabWidget->setTabEnabled(1, false);
        tabWidget->setCurrentIndex(0);
    }
}

void QPropertyWidget::removeMuscle(void)
{
    if (muscleComboBox->currentIndex()>-1)
    {
        emit removeMuscleSignal(muscleComboBox->currentIndex());
    }
}
void QPropertyWidget::removeMuscle(int muscle)
{
    muscleWidgetList[muscle]->hide();
    musclePropertyLayout->removeWidget(muscleWidgetList[muscle]);
    muscleWidgetList.removeAt(muscle);
    muscleComboBox->removeItem(muscle);

    for (int i=0; i<muscleComboBox->count(); ++i)
    {
        muscleComboBox->setItemText(i, muscleComboBox->itemText(i).replace(QRegExp("[0-9]{1,9}"), QString().setNum(i)));
    }

    if (muscleComboBox->currentIndex()<0)
    {
        muscleRemoveButton->setDisabled(true);
        tabWidget->setTabEnabled(2, false);
        tabWidget->setCurrentIndex(0);
    }
}

void QPropertyWidget::removeNerve(void)
{
    if (nerveComboBox->currentIndex()>-1)
    {
        emit removeNerveSignal(nerveComboBox->currentIndex());
    }
}
void QPropertyWidget::removeNerve(int nerve)
{
    nerveWidgetList[nerve]->hide();
    nervePropertyLayout->removeWidget(nerveWidgetList[nerve]);
    nerveWidgetList.removeAt(nerve);
    nerveComboBox->removeItem(nerve);

    for (int i=0; i<nerveComboBox->count(); ++i)
    {
        nerveComboBox->setItemText(i, nerveComboBox->itemText(i).replace(QRegExp("[0-9]{1,9}"), QString().setNum(i)));
    }

    if (nerveComboBox->currentIndex()<0)
    {
        nerveRemoveButton->setDisabled(true);

        tabWidget->setTabEnabled(3, false);
        tabWidget->setCurrentIndex(0);
    }
}

void QPropertyWidget::selectNode(int _node)
{
    this->setType(1);
    for (int i=0; i<nodeWidgetList.length(); ++i)
    {
        nodeWidgetList[i]->hide();
    }

    if (_node>=0)
    {
        nodeComboBox->setCurrentIndex(_node);
        nodeWidgetList[_node]->show();
        emit nodeSelected(_node);

        if (connectionComboBoxList[nodeComboBox->currentIndex()]->currentIndex()>-1) connectionRemoveButton->setDisabled(false);
        else connectionRemoveButton->setDisabled(true);
    }
}
void QPropertyWidget::selectMuscle(int _muscle)
{
    this->setType(2);
    for (int i=0; i<muscleWidgetList.length(); ++i)
    {
        muscleWidgetList[i]->hide();
    }

    if (_muscle>=0)
    {
        muscleComboBox->setCurrentIndex(_muscle);
        muscleWidgetList[_muscle]->show();
        emit muscleSelected(_muscle);
    }
}
void QPropertyWidget::selectNerve(int _nerve)
{
    this->setType(3);
    for (int i=0; i<nerveWidgetList.length(); ++i)
    {
        nerveWidgetList[i]->hide();
    }

    if (_nerve>=0)
    {
        nerveComboBox->setCurrentIndex(_nerve);
        nerveWidgetList[_nerve]->show();
    }
}

void QPropertyWidget::setType(int _type)
{
    tabWidget->setCurrentIndex(_type);
}

void QPropertyWidget::toggleCurve(bool _show)
{
    if (_show) emit addNerveCurve(nerveComboBox->currentIndex());
    else emit removeNerveCurve(nerveComboBox->currentIndex());
}
